//这个条件编译用于防止重复包含头文件。
#ifndef __M_ONLINE_H__
#define __M_ONLINE_H__

#include"util.hpp"
#include<mutex>
#include<unordered_map>

class online_manager
{
private:
    /* data */
    std::unordered_map<uint64_t,wsserver_t::connection_ptr> _hall_user;
    std::unordered_map<uint64_t,wsserver_t::connection_ptr> _room_user;
    //为什么要带锁因为stl容器在实现时并没有带锁，所以如果要在多线程情况下使用stl容器就需要加锁
    std::mutex _mutex;
public:
    //每个调用都需要加锁：因为在访问或者修改时必须是原子的
    //websocket用户进入大厅或者房间进行用户管理
    void enter_hall(uint64_t uid,wsserver_t::connection_ptr& conn)
    {
        std::unique_lock<std::mutex> lock(_mutex);
        _hall_user.insert({uid,conn});
    }
    void enter_room(uint64_t uid,wsserver_t::connection_ptr& conn)
    {
        std::unique_lock<std::mutex> lock(_mutex);
        _room_user.insert({uid,conn});
    }
    //websocket用户退出大厅或者房间进行用户管理
    void exit_hall(uint64_t uid)
    {
        std::unique_lock<std::mutex> lock(_mutex);
        _hall_user.erase(uid);
    }
    void exit_room(uint64_t uid)
    {
        std::unique_lock<std::mutex> lock(_mutex);
        _room_user.erase(uid);
    }
    //判断用户目前是否在游戏大厅还是在游戏中
    bool is_in_hall(uint64_t uid)
    {
        std::unique_lock<std::mutex> lock(_mutex);
        auto fi = _hall_user.find(uid);
        if(fi == _hall_user.end())
        {
            DLOG("user not exists in hall");
            return false;
        }
        DLOG("user exists in hall");
        return true;
    }
    bool is_in_room(uint64_t uid)
    {
        std::unique_lock<std::mutex> lock(_mutex);
        auto fi = _room_user.find(uid);
        if(fi == _room_user.end())
        {
            DLOG("user not exists in room");
            return false;
        }
        DLOG("user exists in room");
        return true;
    }
    //通过用户id获取用户在游戏大厅或者在游戏房间的连接
    wsserver_t::connection_ptr get_conn_from_hall(uint64_t uid)
    {
        //别用代码复用这里：因为多了一次查找，返回时也要查找一次
        //所以还不如直接查找好
        // bool ret = is_in_hall(uid);
        // if(ret == false)
        // {
        //     //返回一个没内容的指针
        //     return wsserver_t::connection_ptr();
        // }
        std::unique_lock<std::mutex> lock(_mutex);
        auto fi = _hall_user.find(uid);
        if(fi == _hall_user.end())
        {
            return wsserver_t::connection_ptr();
        }
        return fi->second;
    }
    wsserver_t::connection_ptr get_conn_from_room(uint64_t uid)
    {
        std::unique_lock<std::mutex> lock(_mutex);
        auto fi = _room_user.find(uid);
        if(fi == _room_user.end())
        {
            return wsserver_t::connection_ptr();
        }
        return fi->second;
    }
};





#endif